package cn.coisini.service.impl;

import cn.coisini.mapper.ArticleMapper;
import cn.coisini.mapper.ArticleTagMapper;
import cn.coisini.model.common.dtos.Result;
import cn.coisini.model.common.enums.ResultEnum;
import cn.coisini.model.common.exception.CustomAuthenticationException;
import cn.coisini.model.dto.ArticleDto;
import cn.coisini.model.dto.CategoryDto;
import cn.coisini.model.dto.UserSearchDto;
import cn.coisini.model.pojo.*;
import cn.coisini.model.vo.QueryVo;
import cn.coisini.model.vo.TagVo;
import cn.coisini.service.ArticleService;
import cn.coisini.service.CategoryService;
import cn.coisini.service.TagService;
import cn.coisini.service.UserService;
import cn.coisini.utils.IdWorker;
import cn.coisini.utils.JwtUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static cn.coisini.model.common.constants.AdminConstants.*;

/**
 * @author xiangshaw
 * Description: 文章实现类
 */
@Service
@RequiredArgsConstructor
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {

    private final UserService userService;
    private final TagService tagService;
    private final CategoryService categoryService;
    private final ArticleTagMapper articleTagMapper;

    // 添加文章
    @Override
    public Result<ResultEnum> addArticle(ArticleDto articleDto) {
        // 1.设置文章的默认属性
        setArticleDefaultProperties(articleDto);
        // 2.确保分类ID有效
        String validCategoryId = ensureValidCategoryId(articleDto.getCategoryId());
        articleDto.setCategoryId(validCategoryId);
        // 3.转换并保存文章
        Article article = new Article();
        BeanUtils.copyProperties(articleDto, article);
        boolean saveSuccess = save(article);
        if (saveSuccess) {
            // 4.保存文章标签关联
            saveArticleTagRelations(article, articleDto);
            return Result.ok(ResultEnum.SUCCESS);
        }
        return Result.error(ResultEnum.FAIL);
    }

    // 保存文章标签关联
    private void saveArticleTagRelations(Article article, ArticleDto articleDto) {
        // 将标签ID字符串转换为列表
        List<String> tagIds = articleDto.getTagIds();
        for (int i = 0; i < tagIds.size(); i++) {
            String tagId = tagIds.get(i);
            String tagName = articleDto.getTagName();
            // 如果标签颜色不存在，使用默认颜色
            String tagColor;
            if (CharSequenceUtil.isNotBlank(articleDto.getTagColor())) {
                tagColor = articleDto.getTagColor().split(",")[i];
            } else {
                tagColor = "#DDBEF6";
            }
            // 根据标签ID查询标签是否存在
            Tag tag = tagService.findById(tagId);
            if (tag == null) {
                // 如果标签不存在，创建新标签
                TagVo tagVo = new TagVo();
                tagVo.setId(String.valueOf(new IdWorker().nextId()));
                tagVo.setTagName(tagName);
                tagVo.setColor(tagColor);
                tagVo.setCreateUser(getCurrentUserId());
                tagService.addTag(tagVo);
                // 更新tagId为新创建的ID
                tagId = tagVo.getId();
            }
            // 保存文章和标签的关联信息
            ArticleTag articleTag = new ArticleTag();
            articleTag.setArticleId(article.getId());
            articleTag.setTagId(tagId);
            articleTagMapper.insert(articleTag);
        }
    }


    // 设置文章的默认属性
    private void setArticleDefaultProperties(ArticleDto articleDto) {
        articleDto.setId(generateId());
        articleDto.setState(articleDto.getState());
        articleDto.setCreateTime(LocalDateTime.now());
        articleDto.setCreateUser(getCurrentUserId());
    }

    // 确保分类ID有效
    private String ensureValidCategoryId(String categoryId) {
        Category category = categoryService.findById(categoryId);
        if (category != null) {
            return categoryId;
        }
        // 检查是否存在“未知分类”
        Category unknownCategory = categoryService.findByName(UNKNOWN_CATEGORY);
        if (unknownCategory != null) {
            return unknownCategory.getId();
        }
        // 创建“未知分类”并返回其ID
        return createUnknownCategory();
    }

    // 创建“未知分类”并返回其ID
    private String createUnknownCategory() {
        CategoryDto categoryDto = new CategoryDto();
        categoryDto.setCategoryName(UNKNOWN_CATEGORY);
        categoryDto.setCategoryAlias("unknown_category");
        // 添加分类并检查结果
        Result<ResultEnum> addResult = categoryService.addCategory(categoryDto);
        if (!addResult.getCode().equals(ResultEnum.SUCCESS.getCode())) {
            throw new CustomAuthenticationException(ResultEnum.FAIL, "无法创建未知分类");
        }
        // 返回新创建的“未知分类”的ID
        Category createdCategory = categoryService.findByName(UNKNOWN_CATEGORY);
        return createdCategory.getId();
    }

    // 生成唯一ID
    private String generateId() {
        return String.valueOf(new IdWorker().nextId());
    }

    // 获取当前用户ID
    private String getCurrentUserId() {
        return JwtUtil.getUserIdFromToken();
    }

    // 获取文章列表
    @Override
    public Result<Object> getArticleList(QueryVo queryVo) {
        // 创建查询条件
        QueryWrapper<Article> wrapper = createArticleQueryWrapper(queryVo);

        // 分页查询文章列表
        Page<Article> page = new Page<>(queryVo.getCurrent(), queryVo.getLimit());
        Page<Article> articlePage = page(page, wrapper);

        // 批量获取用户、分类、状态信息
        Map<String, String> userIdToNameMap = getUserNames(articlePage.getRecords());
        Map<String, String> categoryIdToNameMap = getCategoryNames(articlePage.getRecords());
        // 状态为1已发布，0草稿、2 删除
        Map<String, String> stateMap = getStateMap();
        // 获取文章标签
        Map<String, List<Tag>> articleTagMap = getArticleTagNames(articlePage.getRecords());

        // 设置文章的创建用户名、分类名称、状态 和 标签
        setArticleDetails(articlePage.getRecords(), userIdToNameMap, categoryIdToNameMap, stateMap, articleTagMap);

        return Result.ok(articlePage);
    }

    // 创建文章查询条件
    private QueryWrapper<Article> createArticleQueryWrapper(QueryVo queryVo) {
        QueryWrapper<Article> wrapper = new QueryWrapper<>();
        // 提取查询条件
        String categoryId = queryVo.getCategoryId();
        String state = queryVo.getState();
        String keyword = queryVo.getKeyword();
        String createTimeBegin = queryVo.getCreateTimeBegin();
        String createTimeEnd = queryVo.getCreateTimeEnd();

        // 分类ID模糊查询
        if (CharSequenceUtil.isNotBlank(categoryId)) {
            wrapper = queryWrapperByCategoryId(categoryId);
        }
        // 状态查询
        if (CharSequenceUtil.isNotBlank(state)) {
            wrapper.eq("state", state);
        }
        // 标题或内容模糊查询
        if (CharSequenceUtil.isNotBlank(keyword)) {
            wrapper.like("title", keyword).or().like("content", keyword);
        }
        // 时间区间查询
        if (CharSequenceUtil.isNotBlank(createTimeBegin)) {
            wrapper.ge(CREATE_TIME, createTimeBegin);
        }
        if (CharSequenceUtil.isNotBlank(createTimeEnd)) {
            wrapper.le(CREATE_TIME, createTimeEnd);
        }
        // 创建用户ID和时间倒序排序
        wrapper.eq("create_user", getCurrentUserId())
                .orderByDesc(CREATE_TIME);
        return wrapper;
    }

    // 创建文章查询条件
    private QueryWrapper<Article> queryWrapperByCategoryId(String categoryId) {
        QueryWrapper<Article> wrapper = new QueryWrapper<>();
        // 根据分类名称模糊查询，获取符合条件的分类ID列表
        Category category = categoryService.findById(categoryId);
        wrapper.eq(CATEGORY_ID, category.getId());
        return wrapper;
    }


    // 批量获取用户昵称
    private Map<String, String> getUserNames(List<Article> articles) {
        List<String> userIds = articles.stream()
                .map(Article::getCreateUser)
                .distinct()
                .toList();
        List<User> users = userService.findByIds(userIds);
        return users.stream()
                .collect(Collectors.toMap(User::getId, User::getNickName));
    }

    // 批量获取分类名称
    private Map<String, String> getCategoryNames(List<Article> articles) {
        List<String> categoryIds = articles.stream()
                .map(Article::getCategoryId)
                .distinct()
                .toList();
        List<Category> categories = categoryService.findByIds(categoryIds);
        return categories.stream()
                .collect(Collectors.toMap(Category::getId, Category::getCategoryName));
    }

    // 批量获取状态名称，状态为1已发布，0草稿、2 删除
    private Map<String, String> getStateMap() {
        return Map.of(
                "0", "草稿",
                "1", "已发布",
                "2", "删除"
        );
    }

    // 批量获取文章标签
    private Map<String, List<Tag>> getArticleTagNames(List<Article> articlesIds) {
        // 获取所有文章ID
        List<String> articleIds = articlesIds.stream()
                .map(Article::getId)
                .distinct()
                .toList();
        // 获取所有文章标签
        List<ArticleTag> articleTags = articleTagMapper.selectList(new QueryWrapper<ArticleTag>().in("article_id", articleIds));
        // 获取所有标签ID
        List<String> tagIds = articleTags.stream()
                .map(ArticleTag::getTagId)
                .distinct()
                .toList();
        // 获取所有标签
        if (tagIds.isEmpty()) {
            return Collections.emptyMap();
        }
        List<Tag> tags = tagService.findByIds(tagIds).getData();
        // 通过文章ID分组标签
        return articleTags.stream()
                .collect(Collectors.groupingBy(ArticleTag::getArticleId,
                        Collectors.mapping(tag -> findTagById(tags, tag.getTagId()),
                                Collectors.toList())));
    }

    // 根据标签ID查找标签
    private Tag findTagById(List<Tag> tags, String tagId) {
        return tags.stream()
                .filter(tag -> tag.getId().equals(tagId))
                .findFirst()
                .orElse(null);
    }

    // 设置文章的创建用户名、分类名称、状态、标签
    private void setArticleDetails(List<Article> articles,
                                   Map<String, String> userIdToNameMap,
                                   Map<String, String> categoryIdToNameMap,
                                   Map<String, String> stateMap,
                                   Map<String, List<Tag>> articleTagMap) {
        for (Article article : articles) {
            article.setCreateUser(userIdToNameMap.get(article.getCreateUser()));
            article.setCategoryId(categoryIdToNameMap.get(article.getCategoryId()));
            article.setState(stateMap.get(article.getState()));
            // 设置标签
            List<Tag> tags = articleTagMap.get(article.getId());
            if (tags != null) {
                article.setTagId(tags.stream().map(Tag::getId).collect(Collectors.joining(",")));
                article.setTagName(tags.stream().map(Tag::getTagName).toList());
                // 用逗号拼接标签颜色
                article.setTagColor(tags.stream()
                        .map(Tag::getColor)
                        .collect(Collectors.joining(",")));
            } else {
                article.setTagName(Collections.emptyList());
            }
        }
    }

    // 获取文章详情
    @Override
    public Result<Article> getArticleById(String articleId) {
        Article article = getById(articleId);
        if (article == null) {
            return Result.error(ResultEnum.FAIL, "文章不存在");
        }
        // 批量获取用户、分类、状态信息
        Map<String, String> userIdToNameMap = getUserNames(Collections.singletonList(article));
        Map<String, String> categoryIdToNameMap = getCategoryNames(Collections.singletonList(article));
        // 状态为1已发布，0草稿、2 删除
        Map<String, String> stateMap = getStateMap();
        // 获取文章标签
        Map<String, List<Tag>> articleTagMap = getArticleTagNames(Collections.singletonList(article));

        // 设置文章的创建用户名、分类名称、状态 和 标签
        setArticleDetails(Collections.singletonList(article), userIdToNameMap, categoryIdToNameMap, stateMap, articleTagMap);
        return Result.ok(article);
    }

    // 批量获取文章详情
    @Override
    public List<Article> findByIds(List<String> articleIds) {
        return baseMapper.selectList(new QueryWrapper<Article>().in("id", articleIds));
    }

    // 删除文章
    @Override
    public Result<ResultEnum> deleteArticle(String articleId) {
        int i = baseMapper.deleteById(articleId);
        return i > FALSE ? Result.ok(ResultEnum.SUCCESS) : Result.error(ResultEnum.DATA_DELETE_FAILED);
    }

    // 更新文章
    @Override
    public Result<ResultEnum> updateArticle(ArticleDto articleDto) {
        // 1.更新文章的基本信息
        articleDto.setCategoryId(getArticleCategoryId(articleDto).getId());
        articleDto.setCreateUser(getCurrentUserId());
        articleDto.setUpdateTime(LocalDateTime.now());
        // 2.赋值给实体类
        Article article = new Article();
        BeanUtils.copyProperties(articleDto, article);
        // 3.获取当前文章的标签列表
        QueryWrapper<ArticleTag> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("article_id", article.getId());
        List<ArticleTag> existingTags = articleTagMapper.selectList(queryWrapper);
        // 4.获取现有标签ID列表
        Set<String> existingTagIds = existingTags.stream()
                .map(ArticleTag::getTagId)
                .collect(Collectors.toSet());
        // 5.新的标签ID列表
        Set<String> newTagIds = new HashSet<>(articleDto.getTagIds());
        // 6.找出需要删除的标签
        Set<String> tagsToDelete = new HashSet<>(existingTagIds);
        tagsToDelete.removeAll(newTagIds);
        // 7.找出需要新增的标签
        Set<String> tagsToAdd = new HashSet<>(newTagIds);
        tagsToAdd.removeAll(existingTagIds);
        // 8.执行删除操作
        if (!tagsToDelete.isEmpty()) {
            QueryWrapper<ArticleTag> deleteWrapper = new QueryWrapper<>();
            deleteWrapper.eq("article_id", article.getId())
                    .in("tag_id", tagsToDelete);
            articleTagMapper.delete(deleteWrapper);
        }
        // 9.执行新增操作
        if (!tagsToAdd.isEmpty()) {
            for (String tagId : tagsToAdd) {
                ArticleTag articleTag = new ArticleTag();
                articleTag.setId(String.valueOf(new IdWorker().nextId()));
                articleTag.setTagId(tagId);
                articleTag.setArticleId(article.getId());
                articleTagMapper.insert(articleTag);
            }
        }
        // 10.更新文章信息
        int i = baseMapper.updateById(article);
        if (i <= FALSE) {
            return Result.error(ResultEnum.DATA_UPDATE_FAILED);
        }
        return Result.ok(ResultEnum.SUCCESS);
    }


    /**
     * 获取文章分类ID
     */
    private Category getArticleCategoryId(ArticleDto articleDto) {
        return categoryService.findByName(articleDto.getCategoryId());
    }

    /**
     * 根据分类ID获取文章数量
     */
    @Override
    public long getArticleCountByCategoryId(String categoryId) {
        // 获取文章数量
        return count(new QueryWrapper<Article>().eq(CATEGORY_ID, categoryId));
    }

    /**
     * 根据分类ID列表获取文章列表
     */
    @Override
    public List<Article> getArticleListByIds(List<String> categoryIds) {
        // 检查分类ID列表是否为空
        if (CollUtil.isEmpty(categoryIds)) {
            log.warn("分类ID列表为空，无法获取文章列表。");
            return Collections.emptyList();
        }
        // 根据分类ID列表获取文章列表
        return list(new QueryWrapper<Article>().in(CATEGORY_ID, categoryIds));
    }

    /**
     * 根据标签查询文章列表
     */
    @Override
    public List<Article> getArticleListFromTag(String tagId) {
        QueryWrapper<ArticleTag> articleWrapper = new QueryWrapper<ArticleTag>()
                .eq("tag_id", tagId);
        return articleTagMapper.selectList(articleWrapper).stream()
                .map(articleTag -> getById(articleTag.getArticleId()))
                .filter(Objects::nonNull)
                .toList();
    }

    /**
     * 根据搜索关键词获取文章
     */
    @Override
    public Result<Object> getUserSearchArticle(UserSearchDto userSearchDto) {
        // 获取搜索关键词
        String keyword = userSearchDto.getKeyword();
        if (CharSequenceUtil.isBlank(keyword)) {
            return Result.error(ResultEnum.PARAM_ERROR);
        }
        // 指定查询哪些字段进行匹配
        QueryWrapper<Article> articleQueryWrapper = new QueryWrapper<>();
        articleQueryWrapper
                .like("title", keyword)
                .or()
                .like("content", keyword);
        // 执行查询并分页
        Page<Article> page = new Page<>(userSearchDto.getCurrent(), userSearchDto.getLimit());
        Page<Article> articlePage = page(page, articleQueryWrapper);
        // 封装结果
        Result<Object> result = new Result<>();
        result.setData(articlePage.getRecords());
        return result;
    }

    /**
     * 获取用户文章总数
     * @param userId 用户ID
     * @return 用户总文章数
     */
    @Override
    public long getArticleCountByUserId(String userId, short state) {
        return count(new QueryWrapper<Article>().eq("create_user", userId).eq("state", state));
    }
}
